#include "types.h"
#include "defs.h"
#include "param.h"
#include "mmu.h"
#include "memlayout.h"
#include "x86.h"
#include "proc.h"
#include "spinlock.h"
#include "ptable.h"

extern struct myPtable ptable;
extern int    isInSwapperWorking;
extern int 	  wakeupInswapperFlag;
extern int 	  Debug;

extern int getNumOfFreePages(void);
extern int fileopen(char *path ,int omode , struct file** sf);
extern int fclose(struct file *f, int fd);
extern int fileunlink(char* path);
extern pte_t* myWalkpgdir(pde_t *pgdir, const void *va, int create);
extern int myMappages(pde_t *pgdir, void *la, uint size, uint pa, int perm);
static void swapIn(struct proc* p);
extern void itoa(int n, char* dest);

void
inswapper()
{
	struct proc* p = 0;
	for(;;)
	{
		for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){	//looking for RUNNABLE_SUSPENDED proc
			if(p->state == RUNNABLE_SUSPENDED)
			{

				swapIn(p);
			}
		}

		isInSwapperWorking =  0;
		wakeupInswapperFlag = 0;

		release(&ptable.lock);
		yield();
		acquire(&ptable.lock);
	}
}

void swapIn(struct proc* p)
{
	int fd, i;
	char fname[10], *page;
	struct file* f;

	itoa(p->pid, fname);

	release(&ptable.lock);

	//1. Open the relevant swap file.
	fd = fileopen(fname, 0x000, &f);

	if(Debug == 1)
		cprintf("proc %d start swapIn. fileSwap:%s \n",p->pid,fname);


	acquire(&ptable.lock);

	p->pgdir = setupkvm();

	release(&ptable.lock);
	//2. for each page in the file
	for(i = 0; i < p->sz; i+=PGSIZE)
	{
		//Allocate a new page and copy its content from the file
		page = kalloc();
		fileread(f, page, PGSIZE);

		//Map the page to the page table in the proper location
		myMappages(p->pgdir, (void*)i, PGSIZE, v2p(page), PTE_W | PTE_U);
	}

	fclose(f, fd);
	//Remove the swap file
	fileunlink(fname);

	acquire(&ptable.lock);
	p->state = RUNNABLE;

	if(Debug == 1)
		cprintf("proc %d Finish swapIn. fileSwap:%s \n",p->pid,fname);

}

